import React, {useEffect} from 'react';
import makeStyles from "@material-ui/core/styles/makeStyles";
import Grid from "@material-ui/core/Grid";
import {CircularProgress, Collapse, Fab, Tooltip, Typography, Zoom} from "@material-ui/core";
import IconButton from "@material-ui/core/IconButton";
import {useDispatch, useSelector} from "react-redux";
import HelpIcon from "@material-ui/icons/Help";
import RefreshIcon from "@material-ui/icons/Refresh";
import {
  getAnalysisMethodInputs,
  getAnalysisMethodOutputs,
  getAnalysisMethods,
  getVisualizationMethodsAndTypes,
  selectDeselectAnalysisMethod,
  selectDeselectAnalysisMethodMap
} from "../../../../../../redux/reducers/editor";
import {scrollToTop} from "../../../../../../assets/functions/functions";
import Button from "@material-ui/core/Button";
import MenuSingleSelect from "../../../Common/MenuSingleSelect/MenuSingleSelect";
import AnalysisMappingChoices from "./AnalysisMethodMapping/AnalysisMappingChoices";
import Choices from "./AnalysisMethodParams/Choices";
import TextBox from "./AnalysisMethodParams/TextBox";
import CheckBox from "./AnalysisMethodParams/CheckBox";

const useStyles = makeStyles(theme => ({
  buttonSpacing: {
    marginRight: theme.spacing(1)
  },
  gutterBottom: {
    marginBottom: theme.spacing(2)
  },
}));

export default function Analysis({classes, handleStepBackward, handleStepForward}) {

  // Constants from redux store
  const analysisMethodsData = useSelector(state => state.editor.fetchedData.analysisMethods);
  const analysisMethodInputsData = useSelector(state => state.editor.fetchedData.analysisMethodInputs);
  const activityAttributesData = useSelector(state => state.editor.fetchedData.activityAttributes);
  const selectedAnalysisMethod = useSelector(state => state.editor.selectedData.analysisMethod);
  const selectedMappingAnalysisInputAttributesData = useSelector(state => state.editor.selectedData.mappingAnalysisInputAttributesData);
  const selectedAnalyticsMethodParams = useSelector(state => state.editor.selectedData.analysisMethodParams);

  // Local constants
  const styles = useStyles();
  const dispatch = useDispatch();
  const errorAnalysisMethod = useSelector(state => state.errorMessages.connectionErrors.analysisMethod);
  const errorAnalysisMethodInputsAndParams = useSelector(state => state.errorMessages.connectionErrors.analysisMethodInputs);
  const selectedVisualizationMethod = useSelector(state => state.editor.selectedData.visualizationMethod);

  useEffect(() => {
    scrollToTop();
  }, []);

  const handleRefresh = (errorMessage) => {
    if (errorMessage === "analysisMethod")
      dispatch(getAnalysisMethods());
    if (errorMessage === "inputsAndParams") {
      dispatch(getAnalysisMethodInputs(selectedAnalysisMethod));
      dispatch(getAnalysisMethodOutputs(selectedAnalysisMethod));
    }
  }

  const handleSelectAnalysisMethod = (event, values) => {
    dispatch(selectDeselectAnalysisMethod([values]));
    dispatch(getAnalysisMethodInputs(values));
    dispatch(getAnalysisMethodOutputs(values));
    dispatch(selectDeselectAnalysisMethodMap([]));
  };

  const continueToVisualizations = () => {
    if (Object.values(selectedVisualizationMethod).length === 0)
      dispatch(getVisualizationMethodsAndTypes());
    handleStepForward();
  }

  return (
    <>
      <Grid container direction="column" md={9} lg={8} xl={6}>


        <Typography className={styles.gutterBottom}>
          Analysis methods are like functions. Each analysis methods accepts some inputs
          and provides results as outputs.
        </Typography>

        {analysisMethodsData.length !== 0 ? (
          <Grid item className={styles.gutterBottom}>
            <MenuSingleSelect
              name={"Analysis Methods"}
              dataSource={analysisMethodsData}
              itemName={selectedAnalysisMethod[0]}
              handleChange={handleSelectAnalysisMethod}
            />
          </Grid>
        ) : !errorAnalysisMethod ? (
          <Grid container direction="column" alignItems="center">
            <CircularProgress className={classes.gutterTopBottom}/>
            <Typography variant="overline">Loading analysis inputs and params</Typography>
          </Grid>
        ) : (
          <Grid container justify="center" alignItems="center">
            <Fab color="primary" size="small" className={classes.gutterRight}
                 onClick={() => handleRefresh("analysisMethod")}>
              <RefreshIcon/>
            </Fab>
            <Grid item>
              <Typography>Connection problem, please retry</Typography>
            </Grid>
          </Grid>
        )}

        <Collapse in={selectedAnalysisMethod.length !== 0}>
          {(analysisMethodInputsData.length !== 0 || selectedMappingAnalysisInputAttributesData.length !== 0 ? (
            <>
              <Grid container justify="flex-start" alignItems="center" className={classes.gutterTop}>
                <Grid item>
                  <Typography>Select the <b>Analysis Inputs</b></Typography>
                </Grid>
                <Grid>
                  <Tooltip TransitionComponent={Zoom} arrow placement="right-start" title={
                    <>
                      <Typography  gutterBottom>
                        Analysis inputs accepts data from filters and dataset section
                      </Typography>
                      <Typography>
                        e.g. <b><i>"Activities"</i></b> option consists of a list of all the activities such as a
                        list of course names, a list of resources
                      </Typography>
                    </>
                  }>
                    <IconButton> <HelpIcon/> </IconButton>
                  </Tooltip>
                </Grid>
              </Grid>
              <Grid container className={classes.gutterTopBottom}>
                <Grid item xs={false} sm={1}/>
                <Grid item xs={12} sm={10}>
                  {analysisMethodInputsData.map((analysisInput, index) => {
                    return (
                      <AnalysisMappingChoices
                        key={index}
                        analysisInput={analysisInput}
                        selectedMappingAnalysisInputAttributesData={selectedMappingAnalysisInputAttributesData}
                        classes={classes}
                        activityAttributesData={activityAttributesData}/>
                    )
                  })}
                </Grid>
                <Grid item xs={false} sm={1}/>
              </Grid>
              {selectedAnalyticsMethodParams.length !== 0 ? (
                <>
                  {/*<Grid item>*/}
                  {/*  <Divider className={classes.gutterTopBottom}/>*/}
                  {/*</Grid>*/}
                  <Grid container direction="column">
                    <Grid container justify="flex-start" alignItems="center" className={classes.gutterTop}>
                      <Grid item>
                        <Typography>Select <b>Additional Parameters</b> (optional)</Typography>
                      </Grid>
                      <Grid>
                        <Tooltip TransitionComponent={Zoom} arrow placement="right-start" title={
                          <>
                            <Typography gutterBottom>
                              Predefined additional parameters that can be adjusted (optional)
                            </Typography>
                          </>
                        }>
                          <IconButton> <HelpIcon/> </IconButton>
                        </Tooltip>
                      </Grid>
                    </Grid>
                    <Grid container className={classes.gutterTopBottom}>
                      <Grid item sm={1}/>
                      <Grid item sm={10}>
                        {selectedAnalyticsMethodParams.map((data, index) => {
                          if (data.type === "Choice")
                            return <Choices key={index} classes={classes} paramData={data}
                                            selectedAnalyticsMethodParams={selectedAnalyticsMethodParams}/>;
                          else if (data.type === "Textbox")
                            return <TextBox key={index} paramData={data}
                                            selectedAnalyticsMethodParams={selectedAnalyticsMethodParams}/>;
                          else if (data.type === "Checkbox")
                            return <CheckBox key={index} paramData={data}
                                             selectedAnalyticsMethodParams={selectedAnalyticsMethodParams}/>;
                          else return <></>;
                        })}
                      </Grid>
                      <Grid item sm={1}/>
                    </Grid>
                  </Grid>
                </>
              ) : <></>}
            </>
          ) : !errorAnalysisMethodInputsAndParams ? (
            <Grid container direction="column" alignItems="center">
              <CircularProgress className={classes.gutterTopBottom}/>
              <Typography variant="overline">Loading analysis inputs and params</Typography>
            </Grid>
          ) : (
            <Grid container justify="center" alignItems="center">
              <Fab color="primary" size="small" className={classes.gutterRight}
                   onClick={() => handleRefresh("inputsAndParams")}>
                <RefreshIcon/>
              </Fab>
              <Grid item>
                <Typography>Connection problem, please retry</Typography>
              </Grid>
            </Grid>
          ))}
        </Collapse>

        <Grid container>
          <Button onClick={handleStepBackward} className={styles.buttonSpacing} aria-label="Back">
            Back
          </Button>

          <Button variant="contained" color="primary" aria-label="Next" disabled={selectedAnalysisMethod.length === 0 ||
          analysisMethodInputsData.filter(a => a.required === true).length
          > selectedMappingAnalysisInputAttributesData.length}
                  onClick={continueToVisualizations}>
            Next
          </Button>
        </Grid>

      </Grid>
    </>
  )
};
